﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;

//-----------------------------------------------------------------------------------
//
//  Created: 23:07 2010/6/18    Author:  Arit 
//  Blog:http://www.cnblogs.com/howDo/
//  File: GridViewGroup.cs
//  Description: GridView分组 
//-----------------------------------------------------------------------------------
/// <summary>
/// <
/// </summary>

public class GridViewGroup
{
    public GridViewGroup()
    {
        //
        //TODO: 在此处添加构造函数逻辑
        //
    }
    /// <summary>
    /// 向DataTable中添加 行分组汇总列
    /// </summary>
    /// <param name="olDtable">DataTable</param>
    /// <param name="bjName">分组列</param>
    /// <param name="numColumsStr">需要计算求和的列，用#分割</param>
    /// <returns></returns>
    public static DataTable AddGurop(DataTable olDtable, string bjName, string numColumsStr)
    {

        //为null 或 只有一条记录对于分组来说无意义
        if (olDtable == null)
        {
            return olDtable;
        }
        DataTable table = TableSort(olDtable, bjName);
        Dictionary<int, DataRow> rows = new Dictionary<int, DataRow>();//存放汇总行

        IList<string> numColumns = new List<string>();
        if (numColumsStr == null)
        {
            numColumns = GetNumColumns(table);
        }
        else
        {
            string[] columns = numColumsStr.Split('#');
            foreach (string str in columns)
            {
                numColumns.Add(str);
            }
        }

        string prevDept = table.Rows[0][bjName].ToString();//
        int NoOwn = 0;//同组项的第一行记录的位置
        int index = -1;//索引
        foreach (DataRow item in table.Rows)
        {
            index++;//当前行索引 
            //如果相邻两行 分组标记相同 则继续寻找下行，否则该行为同组的最后一行。进行数据处理
            //item[bjName].ToString() == prevDept 表示为同行 则继续比较下一行
            if (item[bjName].ToString() == prevDept && index != table.Rows.Count - 1)
            {
                continue;
            }
            else if (index == table.Rows.Count - 1)
            {
                if (item[bjName].ToString() != prevDept)
                {
                    DataRow row = CreateGroupRow(table, numColumns, NoOwn, index);
                    rows.Add(index + rows.Count, row);

                    DataRow row2 = table.NewRow();
                    foreach (string columnName in numColumns)
                    {
                        row2[columnName] = item[columnName];
                    }
                    rows.Add(index + rows.Count + 1, row2);
                }
                else
                {
                    DataRow row = CreateGroupRow(table, numColumns, NoOwn, index);
                    rows.Add(index + rows.Count + 1, row);
                }

            }
            else
            {
                prevDept = item[bjName].ToString();//当前分组标记
                DataRow row = CreateGroupRow(table, numColumns, NoOwn, index);
                NoOwn = index;
                rows.Add(index + rows.Count, row);
            }
        }

        DataRow sumRow = CreateSumRow(table, rows, numColumns);

        foreach (int key in rows.Keys)
        {
            table.Rows.InsertAt(rows[key], key);
        }

        table.Rows.Add(sumRow);
        return table;
    }
    /// <summary>
    /// 向DataTable中添加 行分组汇总列
    /// </summary>
    /// <param name="olDtable">DataTable</param>
    /// <param name="bjName">分组列</param> 
    /// <returns></returns>
    public static DataTable AddGurop(DataTable olDtable, string bjName)
    {

        //为null 或 只有一条记录对于分组来说无意义
        if (olDtable == null)
        {
            return olDtable;
        }
        DataTable table = TableSort(olDtable, bjName);
        Dictionary<int, DataRow> rows = new Dictionary<int, DataRow>();//存放汇总行
        IList<string> numColumns = GetNumColumns(table);
        string prevDept = table.Rows[0][bjName].ToString();//
        int NoOwn = 0;//同组项的第一行记录的位置
        int index = -1;//索引
        foreach (DataRow item in table.Rows)
        {
            index++;//当前行索引 
            //如果相邻两行 分组标记相同 则继续寻找下行，否则该行为同组的最后一行。进行数据处理
            //item[bjName].ToString() == prevDept 表示为同行 则继续比较下一行
            if (item[bjName].ToString() == prevDept && index != table.Rows.Count - 1)
            {
                continue;
            }
            else if (index == table.Rows.Count - 1)
            {
                if (item[bjName].ToString() != prevDept)
                {
                    DataRow row = CreateGroupRow(table, numColumns, NoOwn, index);
                    rows.Add(index + rows.Count, row);

                    DataRow row2 = table.NewRow();
                    foreach (string columnName in numColumns)
                    {
                        row2[columnName] = item[columnName];
                    }
                    rows.Add(index + rows.Count + 1, row2);
                }
                else
                {
                    DataRow row = CreateGroupRow(table, numColumns, NoOwn, index);
                    rows.Add(index + rows.Count + 1, row);
                }

            }
            else
            {
                prevDept = item[bjName].ToString();//当前分组标记
                DataRow row = CreateGroupRow(table, numColumns, NoOwn, index);
                NoOwn = index;
                rows.Add(index + rows.Count, row);
            }
        }

        DataRow sumRow = CreateSumRow(table, rows, numColumns);

        foreach (int key in rows.Keys)
        {
            table.Rows.InsertAt(rows[key], key);
        }

        table.Rows.Add(sumRow);
        return table;
    }

    /// <summary>
    /// 生成总计行
    /// </summary>
    /// <param name="table">DataTalbe</param>
    /// <param name="rows">汇总行集合</param>
    /// <param name="numColumns">累计列</param>
    /// <returns>总计行</returns>
    private static DataRow CreateSumRow(DataTable table, Dictionary<int, DataRow> rows, IList<string> numColumns)
    {
        DataRow sumRow = table.NewRow();
        sumRow[0] = "合计";
        foreach (string columnName in numColumns)
        {
            foreach (int key in rows.Keys)
            {
                object count = sumRow[columnName];//汇总行 列值 
                //如果值为null 或 "" 则默认为 0
                if (count == null || count.ToString().Trim() == "")
                {
                    count = 0;
                }
                sumRow[columnName] = decimal.Parse(count.ToString()) + decimal.Parse(rows[key][columnName].ToString());//累加
            }

        }
        return sumRow;
    }

    private static IList<string> GetNumColumns(DataTable table)
    {
        IList<string> numColumns = new List<string>();//存放数字行
        foreach (DataColumn column in table.Columns)
        {
            if (column.DataType == typeof(Decimal) || column.DataType == typeof(Int32)
                 || column.DataType == typeof(Int64) | column.DataType == typeof(float)
                 || column.DataType == typeof(Int64) | column.DataType == typeof(Double)
                )
            {
                numColumns.Add(column.ColumnName);
            }
        }
        return numColumns;
    }
    /// <summary>
    /// 将dataTable排序
    /// </summary>
    /// <param name="olDtable">DataTable</param>
    /// <param name="bjName">排序字段</param>
    /// <returns></returns>
    public static DataTable TableSort(DataTable olDtable, string bjName)
    {
        DataTable table = olDtable.Clone();
        DataRow[] sortRows = olDtable.Select(null, bjName);
        foreach (DataRow item in sortRows)
        {
            table.ImportRow(item);
        }
        return table;
    }
    /// <summary>
    /// 生成汇总行
    /// </summary>
    /// <param name="table">分组表</param>
    /// <param name="numColumns">需要汇总的列</param>
    /// <param name="NoOwn">开始行</param>
    /// <param name="index">结束行</param>
    /// <returns>汇总行</returns>
    private static DataRow CreateGroupRow(DataTable table, IList<string> numColumns, int startRowIndex, int endRowIndex)
    {
        DataRow row = table.NewRow();//汇总行
        //从同组项的第一行记录的位置  到 同组的最后一行
        for (int i = startRowIndex; i < endRowIndex + 1; i++)
        {

            foreach (string columnName in numColumns)
            {

                object count = row[columnName];//汇总行 列值 
                object tempt = table.Rows[i][columnName];//当前行 列值
                //如果值为null 或 "" 则默认为 0
                if (count == null || count.ToString().Trim() == "")
                {
                    count = 0;
                }
                if (tempt == null || tempt.ToString().Trim() == "")
                {
                    tempt = 0;
                }
                row[columnName] = decimal.Parse(count.ToString()) + decimal.Parse(tempt.ToString());//累加
            }
        }
        return row;
    }

    /// <summary>  
    /// 合并单元格 合并一行中的几列  
    /// </summary>  
    /// <param name="GridView1">GridView对象</param>  
    /// <param name="rows">行索引</param>  
    /// <param name="sCol">开始列</param>  
    /// <param name="eCol">结束列</param>  
    public static void GroupRow(GridView gridView, int rows, int sCol, int eCol)
    {
        TableCell oldTc = gridView.Rows[rows].Cells[sCol];
        for (int i = 1; i < eCol - sCol; i++)
        {
            TableCell tc = gridView.Rows[rows].Cells[i + sCol]; 　 //Cells[0]就是你要合并的列  
            tc.Visible = false;
            if (oldTc.ColumnSpan == 0)
            {
                oldTc.ColumnSpan = 1;
            }
            oldTc.ColumnSpan++;
            oldTc.VerticalAlign = VerticalAlign.Middle;
        }
    }
    /// <summary>
    /// 合并列
    /// </summary>
    /// <param name="gv">gridview对象</param>
    /// <param name="cells">列索引</param>
    /// <param name="sRow">合并列开始位置</param>
    /// <param name="eRow">合并列结束位置</param>
    public static void GropCell(GridView gv, int cells, int sRow, int eRow)
    {
        TableCell tc = gv.Rows[sRow].Cells[cells];
        tc.RowSpan = eRow - sRow + 1;
        for (int i = sRow + 1; i <= eRow; i++)
        {
            gv.Rows[i].Cells[cells].Visible = false;
        }
    }
}
